﻿using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Rhino.Mocks;
using TSVNAddin.TSVN;
using TSVNAddin.SVN;
using EnvDTE80;
using EnvDTE;
using TSVNAddin.Config;

namespace TSVNAddin.Core.Test
{
	[TestFixture]
	public class TortoisePathCommandFixture
	{
		[Test]
		public void Execute()
		{
			string workingRoot = @"c:\svn\myproject";
			TortoiseProcCommandType tortoiseCommandType = TortoiseProcCommandType.Update;
			TortoiseProcArgumentType argumentType = TortoiseProcArgumentType.rev;

			var tortoiseProcExecutor = MockRepository.GenerateMock<TortoiseProcExecutor>((ProcessStarter)null, (ConfigStorage)null);
			tortoiseProcExecutor.Expect(x => x.Exec(tortoiseCommandType, workingRoot, argumentType));

			var applicationObject = MockRepository.GenerateMock<DTE2>();

			var workingContext = MockRepository.GenerateMock<WorkingContext>((SolutionAdapter)null, (SVNClientAdapter)null);
			workingContext.Expect(x => x.GetWorkingRoot()).Return(workingRoot);

			var command = new TortoisePathCommand(tortoiseProcExecutor, new RootCommandContext(workingContext), tortoiseCommandType, argumentType);
			command.Execute();

			tortoiseProcExecutor.VerifyAllExpectations();
			workingContext.VerifyAllExpectations();
		}

		[Test]
		public void ShouldReturnVisibleAndEnabledOnQueryStatusWhenRepositoryIsLinked()
		{
			var workingContext = MockRepository.GenerateMock<WorkingContext>((SolutionAdapter)null, (SVNClientAdapter)null);
			workingContext.Expect(x => x.CanExecutePathCommands()).Return(true);

			var command = new TortoisePathCommand(null, new RootCommandContext(workingContext), TortoiseProcCommandType.Update);
			CommandStatus status = command.QueryStatus();

			Assert.AreEqual(CommandStatus.Enabled, status);
		}

		[Test]
		public void ShouldReturnVisibleAndDisabledOnQueryStatusWhenRepositoryIsNotLinked()
		{
			var workingContext = MockRepository.GenerateMock<WorkingContext>((SolutionAdapter)null, (SVNClientAdapter)null);
			workingContext.Expect(x => x.CanExecutePathCommands()).Return(false);

			var command = new TortoisePathCommand(null, new RootCommandContext(workingContext), TortoiseProcCommandType.Update);
			CommandStatus status = command.QueryStatus();

			Assert.AreEqual(CommandStatus.Disabled, status);
		}

		[Test]
		public void OnItemExecute()
		{
			var selectedItemsAdapter = MockRepository.GenerateStub<SelectedItemsAdapter>((DTE2)null);
			selectedItemsAdapter.Stub(x => x.GetSelectedPaths()).Return(new List<string> { "c:\\svn\\pippo.txt" });

			var tortoiseProcExecutor = MockRepository.GenerateMock<TortoiseProcExecutor>(null, null);
			tortoiseProcExecutor.Expect(x => x.Exec(TortoiseProcCommandType.Repostatus, "c:\\svn\\pippo.txt"));

			var command = new TortoisePathCommand(tortoiseProcExecutor, new ItemCommandContext(selectedItemsAdapter, null, new SingleItemCompatibility()), TortoiseProcCommandType.Repostatus);
			command.Execute();

			tortoiseProcExecutor.VerifyAllExpectations();
		}

		[Test]
		public void OnMultipleItemExecute()
		{
			var selectedItemsAdapter = MockRepository.GenerateStub<SelectedItemsAdapter>((DTE2)null);
			selectedItemsAdapter.Stub(x => x.GetSelectedPaths()).Return(new List<string> { "c:\\svn\\pippo.txt", "c:\\svn\\pippo2.txt" });

			var tortoiseProcExecutor = MockRepository.GenerateMock<TortoiseProcExecutor>(null, null);
			tortoiseProcExecutor.Expect(x => x.Exec(TortoiseProcCommandType.Repostatus, "c:\\svn\\pippo.txt*c:\\svn\\pippo2.txt"));

			var command = new TortoisePathCommand(tortoiseProcExecutor, new ItemCommandContext(selectedItemsAdapter, null, new SingleItemCompatibility()), TortoiseProcCommandType.Repostatus);
			command.Execute();

			tortoiseProcExecutor.VerifyAllExpectations();
		}

		[Test]
		public void OnItemOnQueryStatusShouldReturnVisibileAndEnabled()
		{
			var selectedItemsAdapter = MockRepository.GenerateStub<SelectedItemsAdapter>((DTE2)null);
			selectedItemsAdapter.Stub(x => x.GetSelectedPaths()).Return(new List<string> { @"c:\svn\pippo.txt" });

			var workingContext = MockRepository.GenerateMock<WorkingContext>(null, null);
			workingContext.Expect(x => x.CanExecuteCommandsOnPath(@"c:\svn\pippo.txt")).Return(true);

			var command = new TortoisePathCommand(null, new ItemCommandContext(selectedItemsAdapter, workingContext, new SingleItemCompatibility()), TortoiseProcCommandType.Repostatus);
			var status = command.QueryStatus();

			Assert.AreEqual(CommandStatus.Enabled, status);
		}

		[Test]
		public void OnItemOnQueryStatusShouldReturnVisibileAndDisabled()
		{
			var selectedItemsAdapter = MockRepository.GenerateStub<SelectedItemsAdapter>((DTE2)null);
			selectedItemsAdapter.Stub(x => x.GetSelectedPaths()).Return(new List<string> { @"c:\svn\pippo.txt" });

			var workingContext = MockRepository.GenerateMock<WorkingContext>(null, null);
			workingContext.Stub(x => x.CanExecuteCommandsOnPath(@"c:\svn\pippo.txt")).Return(false);

			var command = new TortoisePathCommand(null, new ItemCommandContext(selectedItemsAdapter, workingContext, new SingleItemCompatibility()), TortoiseProcCommandType.Repostatus);
			var status = command.QueryStatus();

			Assert.AreEqual(CommandStatus.Disabled, status);
		}

		[Test]
		public void OnActiveShouldInvokeExecuteTortoiseProcExecutorWithDiffParamWhenExecCalled()
		{
			var document = MockRepository.GenerateMock<ActiveDocumentAdapter>((Document)null);
			document.Stub(x => x.GetFileName()).Return(@"c:\svn\pippo.txt");

			var executor = MockRepository.GenerateMock<TortoiseProcExecutor>((ProcessStarter)null, (ConfigStorage)null);
			executor.Expect(x => x.Exec(TortoiseProcCommandType.Diff, @"c:\svn\pippo.txt"));

			var command = new TortoisePathCommand(executor, new ActiveCommandContext(document, null), TortoiseProcCommandType.Diff);
			command.Execute();

			executor.VerifyAllExpectations();
		}

		[Test]
		public void OnActiveOnQueryStatusShouldReturnVisibleAndEnabledWhenActiveDocumentIsVersionable()
		{
			var document = MockRepository.GenerateMock<ActiveDocumentAdapter>((Document)null);
			document.Stub(x => x.IsVersionable()).Return(true);
			document.Stub(x => x.GetFileName()).Return(@"c:\svn\pippo.txt");

			var workingContext = MockRepository.GenerateMock<WorkingContext>((SolutionAdapter)null, null);
			workingContext.Expect(x => x.CanExecuteCommandsOnPath(@"c:\svn\pippo.txt")).Return(true);

			var command = new TortoisePathCommand(null, new ActiveCommandContext(document, workingContext), TortoiseProcCommandType.Diff);
			CommandStatus status = command.QueryStatus();

			Assert.AreEqual(CommandStatus.Enabled, status);
		}

		[Test]
		public void OnActiveOnQueryStatusShouldReturnVisibleAndDisabledWhenActiveDocumentIsNotVersionable()
		{
			var document = MockRepository.GenerateMock<ActiveDocumentAdapter>((Document)null);
			document.Stub(x => x.IsVersionable()).Return(false);

			var command = new TortoisePathCommand(null, new ActiveCommandContext(document, null), TortoiseProcCommandType.Diff);
			CommandStatus status = command.QueryStatus();

			Assert.AreEqual(CommandStatus.Disabled, status);
		}

		[Test]
		public void OnActiveOnQueryStatusShouldReturnVisibleAndDisabledWhenActiveDocumentIsNotLinkedToWorkingRoot()
		{
			var document = MockRepository.GenerateMock<ActiveDocumentAdapter>((Document)null);
			document.Stub(x => x.IsVersionable()).Return(true);
			document.Stub(x => x.GetFileName()).Return(@"c:\svn\pippo.txt");

			var workingContext = MockRepository.GenerateMock<WorkingContext>((SolutionAdapter)null, null);
			workingContext.Expect(x => x.CanExecuteCommandsOnPath(@"c:\svn\pippo.txt")).Return(false);

			var command = new TortoisePathCommand(null, new ActiveCommandContext(document, workingContext), TortoiseProcCommandType.Diff);
			CommandStatus status = command.QueryStatus();

			Assert.AreEqual(CommandStatus.Disabled, status);

			workingContext.VerifyAllExpectations();
		}
	}
}
